<?
/**
 * 订单类
 */


class Order extends MyBase{
	
	protected $tb_order;
	protected $tb_order_addr;
	protected $tb_order_goods;
	
	protected $tb_paylog;
	protected $tb_order_log;
	protected $tb_order_invoice;
	protected $tb_stock_lack;
	
	protected $orderinfo = array();
	
	function __construct() {
		parent::__construct('order'/*, array('sn' => 'sn', 'consignee' => 'consignee')*/);

		$this->tb_order = $this->get_tbname('order');
		$this->tb_order_addr = $this->get_tbname('order_address');
		$this->tb_order_goods = $this->get_tbname('order_goods');
		
		$this->tb_paylog = $this->get_tbname('paylog');
		$this->tb_order_log = $this->get_tbname('order_log');
		$this->tb_order_invoice = $this->get_tbname('order_invoice');
		
		$this->tb_stock_lack = $this->get_tbname('stock_lack');
	}
	
	// 加入订单
	public function add_to_order($post){
		$payment		= empty($post['payment']) ? '' : trim($post['payment']);
		$delivery		= empty($post['delivery']) ? '' : trim($post['delivery']);
		
		$goods_weight	= empty($post['goods_weight']) ? '' : trim($post['goods_weight']);
		$goods_cost		= empty($post['goods_cost']) ? '' : trim($post['goods_cost']);
		$payment_fee	= empty($post['payment_fee']) ? '' : trim($post['payment_fee']);
		$delivery_fee	= empty($post['delivery_fee']) ? '' : trim($post['delivery_fee']);
		
		$userinfo = & VS::get('userinfo');
		
		// 再次计算金额，防止恶意篡改
		$oCart = & Cart::instance();
		$amount = $oCart->cal_amount($userinfo['userid'], $payment, $delivery);
		if(
			empty($amount) || 
			empty($payment) || empty($delivery) || 
			$goods_weight != $amount['weight'] ||
			$goods_cost != $amount['goods_cost'] ||
			$payment_fee != $amount['payment_fee'] ||
			$delivery_fee != $amount['delivery_fee']
		){
			return $this->rwarn('参数丢失');	// 防止恶意篡改
		}
		
		$sn = get_uuid();	// 生成订单号
		
		// 订单入库
		$orderinfo = array(
			'sn'			=> $sn,
			'userid'		=> $userinfo['userid'],
			'username'		=> $userinfo['username'],
			'consignee'		=> $post['consignee'],
			'weight'		=> $amount['weight'],		// 总重量
			'goods_cost'	=> $amount['goods_cost'],	// 商品总价
			'cost'			=> $amount['cost'],			// 总价
			'payment'		=> $payment,				// 总价
			'payment_fee'	=> $amount['payment_fee'],	// 手续费
			'delivery'		=> $delivery,				// 总价
			'delivery_fee'	=> $amount['delivery_fee'],	// 配送费用
			'memo'			=> trim($post['memo']),
			//'addrid'		=> $addrid,					// 去掉
		
			'state'			=> 0,						// 订单状态
			'payment_state'	=> 0,						// 支付状态
			'delivery_state'=> 0,						// 配送状态
			'addtime'		=> TIME,
		);
		$orderid = $this->db->insert($this->tb_order, $orderinfo);
		if($orderid > 0){

			// 增加一条消息
			$oNotice = new Notice();
			$oNotice->add(Notice::NEW_ORDER, $orderid);
			
			// 收货地址
			$oAddress = new Address();
			$province_name = $oAddress->get_province_by_id($post['province_id']);
			$city_name = $oAddress->get_city_by_id($post['city_id']);
			$area_name = $oAddress->get_area_by_id($post['area_id']);
			$data = array(
				'orderid'		=> $orderid,	// 废弃，仅保留sn
				'sn'			=> $sn,
				'userid'		=> $userinfo['userid'],
				'username'		=> $userinfo['username'],
				'consignee'		=> $post['consignee'],
				'province_id'	=> $post['province_id'],
				'province_name'	=> $province_name,
				'city_id'		=> $post['city_id'],
				'city_name'		=> $city_name,
				'area_id'		=> $post['area_id'],
				'area_name'		=> $area_name,
				'address'		=> $post['address'],
				'mobile'		=> $post['mobile'],
				'tel'			=> $post['tel'],
				'email'			=> $post['email'],
				'zipcode'		=> $post['zipcode'],
				'zipcode'		=> $post['zipcode'],
				'besttime'		=> $post['besttime'],
			);
			$addrid = $this->db->insert($this->tb_order_addr, $data);
			
			// 转移购物车商品
			$oGoods = & Goods::instance();
			foreach($amount['cartlist'] as $goods){
				$data = array(
					'orderid'	=> $orderid,		// 废弃，仅保留sn
					'sn'		=> $sn,
					// 'userid'	=> $userinfo['userid'],
					'goodsid'	=> $goods['goodsid'],
					'goodsname'	=> $goods['goods_name'],
					'price'		=> $goods['price'],
					'number'	=> $goods['number'],
					'specs'		=> serialize($goods['specs']),
					'fspecs'	=> serialize($goods['fspecs']),
					'addtime'	=> TIME,
					'cost'		=> $goods['cost'],
				);
				$this->db->insert($this->tb_order_goods, $data);
				// 销售数量+1
				$oGoods->inc_trends($goods['goodsid'], 'sales', $goods['number']);
			}
			// 删除购物车
			$oCart->clear_cart($userinfo['userid']);
			$orderinfo['id'] = $orderid;			
			return $this->rsucc('', $orderinfo, 'orderinfo');
		}
		return $this->rfail('数据库错误');
	}

	public function get_order_goods($sn, $goodsid, $detail = false){
		$goods = $this->db->get_row($this->tb_order_goods, array('sn' => $sn, 'goodsid' => $goodsid), '*');
		if(!empty($goods) && $detail == true){
			$oGoods = & Goods::instance();
			$goods['goodsinfo'] = $oGoods->get_row($goods['goodsid'], '*');
			$goods['specs'] = unserialize($goods['specs']);
			$goods['fspecs'] = unserialize($goods['fspecs']);
			$goods['ftime'] = ftime($goods['addtime']);
		}
		return $goods;
	}
	
	public function get_order_goods_all($sn, $detail = false){
		$list = $this->db->get_all($this->tb_order_goods, '*', array('sn' => $sn));
		$goodslist = array();
		if(!empty($list['list']) && $detail == true){
			$oGoods = & Goods::instance();
			foreach($list['list'] as $key => $goods){
				$goods['goodsinfo'] = $oGoods->get_row($goods['goodsid'], '*');
				$goods['specs'] = unserialize($goods['specs']);
				$goods['fspecs'] = unserialize($goods['fspecs']);
				$goods['ftime'] = ftime($goods['addtime']);
				$goodslist[$goods['goodsid']] = $goods;
			}
		}
		return $goodslist;
	}
	
	/*public function get_address($addrid, $fields = '*'){
		return $this->db->get_row($this->tb_order_addr, array('id' => $addrid), $fields);
	}*/
	
	public function get_order_address($sn, $fields = '*'){
		return $this->db->get_row($this->tb_order_addr, array('sn' => $sn), $fields);
	}
		
	/**
	 * 取一条记录
	 */
	public function get_row($id, $fields = '*'){
		if(!empty($this->orderinfo) && $this->orderinfo['id'] == $id){
			return $this->orderinfo;
		}
		$orderinfo = $this->db->get_row($this->tb_order, array('id' => $id), $fields);
		if($fields == '*'){
			$this->orderinfo = $orderinfo;
		}
		return $orderinfo;
	}
	
	// 一般情况下，传递SN的都是单一订单信息
	public function get_order_by_sn($sn, $fields = '*'){
		if(!empty($this->orderinfo) && $this->orderinfo['sn'] == $sn){
			return $this->orderinfo;
		}
		$orderinfo = $this->db->get_row($this->tb_order, array('sn' => $sn), $fields);
		if($fields == '*'){
			$this->orderinfo = $orderinfo;
		}
		return $orderinfo; 
	}
	
	/**
	 * 取列表
	 */
	public function get_list($fields = '*', $select = array(), $order = array(), $page = 1, $size = 10, $offset = PAGE_OFFSET){
		$where = array();
		$like = array();

		// 指定用户
		if(!empty($select['userid'])){			$where[] = "`o`.`userid`='{$select['userid']}'";						}

		if(!empty($select['keyword'])){
			$select['sn']			= $select['keyword'];
			$select['consignee']	= $select['keyword'];
			$select['goodsname']	= $select['keyword'];
		}
		if(!empty($select['sn'])){				$like[] = "`o`.`sn` LIKE '%{$select['sn']}%'";							}
		if(!empty($select['username'])){		$like[] = "`o`.`username` LIKE '%{$select['username']}%'";				}
		if(!empty($select['consignee'])){		$like[] = "`o`.`consignee` LIKE '%{$select['consignee']}%'";			}

		// 价格
		if(!empty($select['cost_min'])){		$where[] = "`o`.`cost`>={$select['cost_min']}";							}
		if(!empty($select['cost_max'])){		$where[] = "`o`.`cost`<={$select['cost_max']}";							}
		// 支付配送方式
		if(!empty($select['payment'])){			$where[] = "`o`.`payment`='{$select['payment']}'";						}
		if(!empty($select['payment_state'])){	$where[] = "`o`.`payment_state`='{$select['payment_state']}'";			}
		if(!empty($select['delivery'])){		$where[] = "`o`.`delivery`='{$select['delivery']}'";					}
		if(!empty($select['delivery_state'])){	$where[] = "`o`.`delivery_state`='{$select['delivery_state']}'";		}

		if(!empty($select['goodsname'])){			
			$like[] = " EXISTS (SELECT `orderid` FROM `{$this->tb_order_goods}` AS `g` WHERE `g`.`orderid`=`o`.`id` AND `g`.`goodsname` LIKE '%{$select['goodsname']}%')";
		}
		if(!empty($like)){
			$where[] = '('.(implode(' OR ', $like)).')';
		}
		$where[] = "`o`.`isdel`=0";	// 只显示未删除
		if(empty($where)){
			$where = '';
		}else{
			$where = " WHERE ".trim(implode(' AND ', $where));
		}

		// 排序
		$orderby = array();
		if(!empty($order)){
			$allfields = $this->db->get_fields($this->tb_order);
			foreach ($order as $field => $direction){
				if(!in_array($direction, array('ASC', 'DESC', 'asc', 'desc')))continue;
				switch ($field) {
					case 'orderby_price':
						$orderby[] = "`o`.`price` {$direction}";
						break;
					
					default:
						if(array_key_exists($field, $allfields)){
							$orderby[] = "`o`.`{$field}` {$direction}";
						}
						break;
				}
			}
		}
		if(empty($orderby)){
			$orderby[] = "`o`.`id` DESC";
		}
		$orderby = implode(',', $orderby);

		$sql = <<<SQL
SELECT SQL_CALC_FOUND_ROWS {$fields} FROM `{$this->tb_order}` AS `o`
	{$where}
	ORDER BY {$orderby} 
SQL
;
		$list = $this->db->sql_list($sql, $page, $size, $offset);
		/* if(!empty($list['list'])){
			//$oGoods = & Goods::instance();
			foreach($list['list'] as $key => $row){
				$row['goodslist'] = $this->get_order_goods_all($row['sn'], $detail = true);
				$row['address'] = $this->get_order_address($row['sn']);
				$row['ftime'] = ftime($row['addtime']);
				$list['list'][$key] = $row;
			}
		} */
		return $list;
	}
	
	public function get_send_list($fields = '*', $select = array(), $order = array(), $page = 1, $size = 10, $offset = PAGE_OFFSET){
		$where = array("`o`.`payment_state`=2");
		if(!empty($select['sn'])){
			$where[] = "`o`.`sn` LIKE '%{$select['sn']}%'";
		}
		if(isset($select['isprepare']) && $select['isprepare'] !== ''){
			$where[] = "`o`.`delivery_state`={$select['isprepare']}";
		}
		$where = implode(' AND ', $where);
		// 排序
		$orderby = array();
		if(!empty($order)){
			$allfields = $this->db->get_fields($this->tb_order);
			foreach ($order as $field => $direction) {
				if(!in_array($direction, array('ASC', 'DESC', 'asc', 'desc')))continue;
				if(array_key_exists($field, $allfields)){
					$orderby[] = "`o`.`{$field}` {$direction}";
				}
			}
		}
		if(empty($orderby)){
			$orderby[] = "`o`.`id` DESC";
		}
		$orderby = implode(',', $orderby);

		$sql = <<<SQL
SELECT `g`.*,`o`.`username` FROM 
	`tb_order_goods` `g` 
	INNER JOIN `tb_order` `o` 
		ON `g`.orderid = `o`.id 
	WHERE {$where}
	ORDER BY {$orderby}
SQL
;
		$goodslist = $this->db->sql_list($sql, $page, $size, $offset);
		if(!empty($goodslist)){
			$oGoods = & Goods::instance();
			foreach($goodslist['list'] as $key => $goods){
				$goods['goodsinfo'] = $oGoods->get_row($goods['goodsid'], '*');
				$goods['specs'] = unserialize($goods['specs']);
				$goods['fspecs'] = unserialize($goods['fspecs']);
				// $goods['addtime'] = ftime($goods['addtime']);
				// 收货人信息
				$goods['address'] = $this->get_order_address($goods['sn']);
				$goodslist['list'][$key] = $goods;
			}
		}
		return $goodslist;
	}

	public function get_invoice_by_express_no($express_no, $fields = '*'){
		return $this->db->get_row($this->tb_order_invoice, array('express_no' => $express_no), $fields);
	}
	
	public function get_invoice_list($fields = '*', $select = array(), $order = array(), $page = 1, $size = 10, $offset = PAGE_OFFSET){
		$list = $this->db->get_list($this->tb_order_invoice, $fields, $select, $order, $page, $size, $offset);
		if(!empty($list['list'])){
			$oGoods = & Goods::instance();
			foreach($list['list'] as $key => $row){
				$goodsids = empty($row['goods_shipped']) ? null : explode(',', $row['goods_shipped']);
				if(empty($goodsids)){
					$row['goodslist'] = $this->get_order_goods_all($row['sn'], $detail = true);
				}else{
					$row['goodslist'] = array();
					foreach ($goodsids as $goodsid) {
						$goods = $this->get_order_goods($row['sn'], $goodsid, true);
						$goods['goodsinfo'] = $oGoods->get_row($goodsid, '*');
						$row['goodslist'][] = $goods;
					}
				}
				$row['address'] = $this->get_order_address($row['sn']);
				// $row['ftime'] = ftime($row['addtime']);
				$list['list'][$key] = $row;
			}
		}
		return $list;
	}
	
	/*******************************************************************************
	 * 缺货商品列表
	 *******************************************************************************/
	public function get_lack_list($fields = '*', $select = array(), $order = array(), $page = 1, $size = 10, $offset = PAGE_OFFSET){
		$goodslist = $this->db->get_list($this->tb_stock_lack, $fields, $select, $order, $page, $size, $offset);
		if(!empty($goodslist)){
			$oGoods = & Goods::instance();
			$prototypes = Prototype::get_prototypes();
			foreach($goodslist['list'] as $key => $goods){
				$goods['goodsinfo'] = $oGoods->get_row($goods['goodsid'], '*');
				// 规格信息
				$goods['specinfo'] = $prototypes[$goods['prototypeid']];
				$goods['specname'] = $prototypes[$goods['prototypeid']]['value'][$goods['value']];
				// 库存信息
				$goods['stockinfo'] = $oGoods->get_spec($goods['goodsid'], $goods['prototypeid'], $goods['value'], $fields = '`quantity`,`autofill`');
				if(empty($goods['stockinfo'])){
					$goods['stockinfo'] = array('quantity' => 0);
				}else{
					if($goods['stockinfo']['autofill'] == 1){
						$goods['stockinfo']['quantity'] = $goods['goodsinfo']['quantity'];
					}
				}
				// $goods['addtime'] = ftime($goods['addtime']);
				
				$goodslist['list'][$key] = $goods;
			}
		}
		return $goodslist;
	}
	
	/***************************************************************************
	 * 订单相关操作
	 ***************************************************************************/
	
	public function update($sn, $data, $condition = ''){
		$select = array('sn' => trim($sn));
		if(!empty($condition)){
			$select['kept'] = $condition;
		}
		$date['updatetime'] = TIME;
		if(!empty($this->orderinfo)){
			array_update($this->orderinfo, $data);
		}
		return $this->db->update($this->tb_order, $select, $data);
	}

	public function edit($post){
		$subAction = trim($post['subAction']);
		/**
		 * 订单操作比较多，又不想多开页面，此处作为统一入口，在此要加上权限判断
		 */
		$r = 0;
		$orderinfo = $this->get_row($post['id']);
		
		switch($subAction){
			case 'confirm':
				$r = $this->confirm($orderinfo['sn']);
				break;
			case 'cancel':
				if(empty($post['memo'])){
					return $this->rwarn('取消订单必须备注');
				}
				$r = $this->cancel($orderinfo['sn']);
				break;
			case 'invalid':
				if(empty($post['memo'])){
					return $this->rwarn('设订单无效必须备注');
				}
				$r = $this->invalid($orderinfo['sn']);
				break;
			case 'pay':
				if(empty($post['memo'])){
					return $this->rwarn('确认付款必须备注');
				}
				$r = $this->pay($orderinfo['sn']);
				break;
			case 'prepare':
				$r = $this->prepare($orderinfo['sn']);
				break;
			case 'send':
				if(empty($post['express_no'])){
					return $this->rwarn('未输入快递单号');
				}
				$post['list'] = empty($post['list']) ? array() : $post['list'];
				$r = $this->send($orderinfo['sn'], $post['express_no'],  $post['express_fee'], $post['list']);
				break;
			case 'complete':
				$r = $this->complete($orderinfo['sn']);
				break;
			case 'lack':
				$post['list'] = empty($post['list']) ? array() : $post['list'];
				$r = $this->lack($orderinfo['sn'], $post['list']);
				break;
		}
		if(is_array($r)){
			return $r;
		}
		if($r > 0){	// 添加日志
			$fstate = array(
				's'		=> $orderinfo['state'],
				'p'		=> $orderinfo['payment_state'],
				'd'		=> $orderinfo['delivery_state'],
			);
			$this->action_log($orderinfo['sn'], 1, $subAction, $fstate, $post['memo']);
		}
		return $this->rjust($r);
	}
	
	public function confirm($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] == -2){
			return $this->rfail('当前订单已为无效订单');
		}
		if($orderinfo['state'] == -1){
			return $this->rwarn('当前订单已取消，请先恢复');
		}
		if($orderinfo['state'] > 0){
			return $this->rwarn('当前订单已确认过');
		}
		return $this->update($sn, array(
			'state'			=> 1,
			'confirm_time'	=> TIME,
		), " AND `state`=0");
	}
	
	public function cancel($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['payment_state'] == 2){
			return $this->rwarn('当前订单已付款成功，请先退款');
		}
		if($orderinfo['delivery_state'] == 2){
			return $this->rwarn('当前订单已发货，请先退货');
		}
		return $this->update($sn, array(
			'state'			=> -1,
			'confirm_time'	=> TIME,
		), " AND `payment_state`<2 AND `delivery_state`<2");
	}
	
	public function invalid($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['payment_state'] == 2){
			return $this->rwarn('当前订单已付款成功，请先退款');
		}
		if($orderinfo['delivery_state'] == 2){
			return $this->rwarn('当前订单已发货，请先退货');
		}
		return $this->update($sn, array(
			'state'			=> -2,
			'confirm_time'	=> TIME,
		), " AND `payment_state`<2 AND `delivery_state`<2");
	}
	
	public function pay($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 0){
			return $this->rwarn('当前订单已取消或无效');
		}
		if($orderinfo['payment_state'] == 2){
			return $this->rwarn('当前订单已付款成功，已确认');
		}
		return $this->update($sn, array(
			'state'			=> 1,	// 已付款的订单自动确认
			'confirm_time'	=> $orderinfo['state'] == 0 ? TIME : $orderinfo['confirm_time'],
			'payment_state'	=> 2,
			'payment_time'	=> TIME,
		), " AND `state`>=0 AND `payment_state`<2");
	}
	
	public function prepare($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 0){
			return $this->rwarn('当前订单已取消或无效');
		}
		if($orderinfo['delivery_state'] > 0){
			return $this->rwarn('当前订单已配过货了');
		}
		// 检查商品库存
		$check = $this->check_store($sn);
		if(!empty($check)){
			return $this->rwarn('部分商品库存不足');
		}
		
		return $this->update($sn, array(
			'state'			=> 1,	// 已配货的订单自动确认
			'confirm_time'	=> $orderinfo['state'] == 0 ? TIME : $orderinfo['confirm_time'],
			'delivery_state'=> 1,
			'delivery_time'	=> TIME,
		), " AND `state`>=0 AND `delivery_state`=0");
	}
	
	public function send($sn, $express_no, $express_fee, $goodsids = array()){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 0){
			return $this->rwarn('当前订单已取消或无效');
		}
		if($orderinfo['delivery_state'] == 0){
			return $this->rwarn('未配货，不能发货');
		}
		if($orderinfo['delivery_state'] >= 2){
			return $this->rwarn('当前订单已全部发过货了');
		}
		// 检查商品库存
		$check = $this->check_store($sn, $goodsids);
		if(!empty($check)){
			return $this->rwarn('部分商品库存不足');
		}
		$express_info = $this->get_invoice_by_express_no($express_no, 'id');
		if(!empty($express_info)){
			return $this->rwarn('相同发货单号已存在，请检查是否已经发过货了');
		}
		
		// 保存发货单
		$invoice_sn = get_uuid();	// 生成发货单号
		$goods_cost = $this->count_cost($sn, $goodsids);
		$goods_shipped = empty($goodsids) ? '' : implode(',', $goodsids);
		$data = array(
			'invoice_sn'	=> $invoice_sn,
			'orderid'		=> $orderinfo['id'],
			'sn'			=> $orderinfo['sn'],
			'userid'		=> $orderinfo['userid'],
			'username'		=> $orderinfo['username'],
			'delivery'		=> $orderinfo['delivery'],
			'express_no'	=> $express_no,
			'express_fee'	=> $express_fee,
			'goods_shipped'	=> $goods_shipped,
			'goods_cost'	=> $goods_cost,
			'state'			=> 0,
			'addtime'		=> TIME,
		);
		$invoice_id = $this->db->insert($this->tb_order_invoice, $data);
		if($invoice_id <= 0){
			return $invoice_id;
		}
		// 减库存
		if(STOCK_REDUCE_TIME == 'send'){
			$this->reduce_store($sn, $goodsids);
		}
		$order_goods_count = $this->db->get_counts($this->tb_order_goods, array('sn' => $sn));
		$order_goods_shipped = $this->db->get_counts($this->tb_order_goods, array('sn' => $sn, 'kept' => " AND `sentnum`>0 "));
		if($order_goods_count == $order_goods_shipped){
			if($orderinfo['payment'] == 'ALIPAY'){	// 支付宝担保支付，发货接口
				$__orderinfo = $orderinfo;
				$__payments = cache_read('payments.php');
				$__payment_info = $__payments[$orderinfo['payment']];
				// 配送方式
				$__deliverys = cache_read('deliverys.php');
				$__delivery_info = $__deliverys[$__orderinfo['delivery']];
				include_once PAY_PTH."alipay/alipayapi.send.php";
			}
			// 全部商品已发货，更新订单状态
			return $this->update($sn, array(
				'delivery_state'=> 2,
				'islack'		=> 0,	// 全部发货成功，则肯定不缺货了
				'delivery_time'	=> TIME,
			), " AND `state`=1 AND `delivery_state`=1");
		}
		return true;
	}
		
	public function complete($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 0){
			return $this->rwarn('当前订单已取消或无效');
		}
		if($orderinfo['payment_state'] < 2){
			return $this->rwarn('当前订单还未付款成功');
		}
		if($orderinfo['delivery_state'] < 2){
			return $this->rwarn('当前订单还未发货');
		}
		$select = array('sn' => trim($sn), 'kept' => " AND `state`>=0 AND `payment_state`=2 AND `delivery_state`>=2");
		return $this->update($sn, array(
				'state'			=> 2,
				'delivery_state'=> 3,	// 必须是已收货
				'confirm_time'	=> TIME,
				'delivery_time'	=> TIME,
		));
	}
	
	public function lack($sn, $goodsids){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 0){
			return $this->rwarn('当前订单已取消或无效');
		}
		if($orderinfo['delivery_state'] >= 2){
			return $this->rwarn('当前订单已发货，无需登记');
		}
		if($orderinfo['islack'] == 1){
			return $this->rwarn('当前订单已进行过缺货登记');
		}
		// 检查商品库存
		$lack_arr = $this->check_store($sn, $goodsids, $detail = true);
		if(empty($lack_arr)){
			return $this->rwarn('当前订单不存在缺货问题');
		}
		$oGoods = & Goods::instance();
		foreach($lack_arr as $lackinfo){
			$data = array(
				'goodsid'		=> $lackinfo['goodsid'],
				'prototypeid'	=> $lackinfo['prototypeid'],
				'value'			=> $lackinfo['value'],
				'orderid'		=> $orderinfo['id'],
				'sn'			=> $sn,
				'userid'		=> $orderinfo['userid'],
				'username'		=> $orderinfo['username'],
				'quantity'		=> $lackinfo['quantity'],
			);
			$select = array(
				'goodsid'		=> $lackinfo['goodsid'],
				'prototypeid'	=> $lackinfo['prototypeid'],
				'value'			=> $lackinfo['value'],
				'sn'			=> $sn,
			);
			$lackrs = $this->db->get_row($this->tb_stock_lack, $select, 'id');
			if(empty($lackrs)){
				$data['addtime'] = TIME;
				$this->db->insert($this->tb_stock_lack, $data);
			}else{
				$data['updatetime'] = TIME;
				$this->db->update($this->tb_stock_lack, $select, $data);
			}
			
			// 缺货登记，库存表
			$oGoods->lack($lackinfo['goodsid'], $lackinfo['prototypeid'], $lackinfo['value']);
		}
				
		// 标记订单缺货		
		return $this->update($sn, array(
				'islack'		=> 1,
		), " AND `state`>=0 AND `delivery_state`<2");
	}
	
	public function action_log($sn, $type, $action, $fstate, $memo = ''){
		$orderinfo = $this->get_order_by_sn($sn);
		// if($type == 1){
		// 	$userinfo = & VS::get('managerinfo');
		// }else{
			$userinfo = & VS::get('userinfo');
		// }
		$tstate = array(
			's'		=> $orderinfo['state'],
			'p'		=> $orderinfo['payment_state'],
			'd'		=> $orderinfo['delivery_state'],
		);
		$data = array(
			'orderid'	=> $orderinfo['id'],
			'sn'		=> $orderinfo['sn'],
			'type'		=> $type,
			'userid'	=> $userinfo['userid'],
			'username'	=> $userinfo['username'],
			'action'	=> $action,
			'fstate'	=> json_encode($fstate),
			'tstate'	=> json_encode($tstate),
			'time'		=> TIME,
			'memo'		=> $memo,
		);
		return $this->db->insert($this->tb_order_log, $data);
	}
	
	
	
	/***************************************************************************
	 * 前台操作入口
	 ***************************************************************************/
	
	public function acts($sn, $subAction, $post){
		$r = 0;
		$orderinfo = $this->get_order_by_sn($sn);
		
		switch($subAction){
			case 'receive':
				$r = $this->receive($sn);
				break;
			case 'cancel':
				if(empty($post['memo'])){
					return $this->rwarn('取消订单必须备注');
				}
				$r = $this->cancel($sn);
				break;
			case 'lack':
				// 前台缺货登记，未完成
				break;
		}
		if(is_array($r)){
			return $r;
		}
		if($r > 0){	// 添加日志
			$fstate = array(
					's'		=> $orderinfo['state'],
					'p'		=> $orderinfo['payment_state'],
					'd'		=> $orderinfo['delivery_state'],
			);
			$this->action_log($sn, 0, $subAction, $fstate, $post['memo']);
		}
		return $this->rjust($r);
	}
	
	public function receive($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 0){
			return $this->rwarn('当前订单已取消或无效');
		}
		if($orderinfo['delivery_state'] < 2){
			return $this->rwarn('当前订单还未发货');
		}
		if($orderinfo['payment_state'] == 2){
			return $this->complete($sn);
		}

		// 增加一条消息
		$oNotice = new Notice();
		$oNotice->add(Notice::RECEIVE, $orderinfo['id']);

		$select = array('sn' => trim($sn), 'kept' => " AND `state`>=0 AND `delivery_state`=2");
		return $this->update($sn, array(
				'delivery_state'=> 3,
				'delivery_time'	=> TIME,
		));
	}
	
	public function commented($sn){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['state'] < 2){
			return $this->rwarn('当前订单还未完成，不能评价');
		}

		// 增加一条消息
		$oNotice = new Notice();
		$oNotice->add(Notice::COMMENTED, $orderinfo['id']);

		$select = array('sn' => trim($sn), 'kept' => " AND `state`=2");
		return $this->update($sn, array(
			'state'=> 3,
			'confirm_time'	=> TIME,
		));
	}

	/*******************************************************************************
	 * 计算给定商品的金额
	 *******************************************************************************/
	public function count_cost($sn, $goodsids = array()){
		if(empty($goodsids)){
			// 取订单中商品信息
			$goodslist = $this->get_order_goods_all($sn, $detail = false);
		}else{
			$goodslist = array();
			foreach ($goodsids as $goodsid) {
				$goodslist[] = $this->get_order_goods($sn, $goodsid, false);
			}
		}
		$cost = 0;
		foreach($goodslist as $goods){
			$cost += $goods['cost'];
		}
		return $cost;
	}
	
	/***************************************************************************
	 * 库存相关操作
	 ***************************************************************************/
	
	/**
	 * 检查库存
	 * @param string $sn
	 */
	public function check_store($sn, $goodsids = array(), $detail = false){
		if(empty($goodsids)){
			// 取订单中商品信息
			$goodslist = $this->get_order_goods_all($sn, $detail = true);
		}else{
			$goodslist = array();
			foreach ($goodsids as $goodsid) {
				$goodslist[] = $this->get_order_goods($sn, $goodsid, true);
			}
		}
		// 合并需要的规格数量
		$spec_needs = array();
		foreach($goodslist as $goods){
			if(!isset($spec_needs[$goods['goodsid']])){
				$spec_needs[$goods['goodsid']] = array('quantity' => $goods['goodsinfo']['quantity']);
			}
			foreach($goods['specs'] as $prototypeid => $spec){
				if(empty($spec_needs[$goods['goodsid']][$prototypeid])){
					$spec_needs[$goods['goodsid']][$prototypeid] = array();
				}
				if(empty($spec_needs[$goods['goodsid']][$prototypeid][$spec])){
					$spec_needs[$goods['goodsid']][$prototypeid][$spec] = $goods['number'];
				}else{
					$spec_needs[$goods['goodsid']][$prototypeid][$spec] += $goods['number'];
				}
			}
		}
	
		$oGoods = & Goods::instance();
		$lack_arr = array();
		foreach($spec_needs as $goodsid => $spec_need){
			// 取对应商品的库存信息
			foreach($spec_need as $prototypeid => $spec){
				if(!is_array($spec))continue;
				foreach($spec as $value => $number){
					$goods_spec = $oGoods->get_spec($goodsid, $prototypeid, $value);
					if(empty($goods_spec)){
						$quantity = 0;
					}elseif($goods_spec['autofill'] == 1){
						$quantity = $spec_need['quantity'];
					}else{
						$quantity = $goods_spec['quantity'];
					}
					if($quantity < $number){
						if($detail == false){
							return $lack_arr;
						}else{
							$lack_arr[] = array(
								'sn'			=> $sn,	// 貌似多余
								'goodsid'		=> $goodsid,
								'prototypeid'	=> $prototypeid,
								'value'			=> $value,
								'quantity'		=> $number - $quantity,
							);
						}
					}
				}
			}
	
		}
		return $lack_arr;
	}
	
	/**
	 * 减库存
	 * 目前的机制是订单里的商品只要一件缺都不发货
	 * @param string $sn
	 */
	public function reduce_store($sn, $goodsids = array()){
		if(empty($goodsids)){
			// 取订单中商品信息
			$goodslist = $this->get_order_goods_all($sn, $detail = true);
		}else{
			$goodslist = array();
			foreach ($goodsids as $goodsid) {
				$goodslist[] = $this->get_order_goods($sn, $goodsid, true);
			}
		}

		$oGoods = & Goods::instance();
		foreach($goodslist as $goods){
			if($goods['sentnum'] > 0)continue;	// 已发过货
			// 更新商品信息表
			$quantity = $goods['goodsinfo']['quantity'] - $goods['number'];
			$oGoods->update($goods['goodsid'], array('quantity' => $quantity));
			// 更新订单商品表
			$this->db->update($this->tb_order_goods, array('sn' => $sn, 'goodsid' => $goods['goodsid']), array(
				'sentnum'	=> $goods['number'],
				'senttime'	=> TIME,
			));
			// 更新商品库存表
			foreach($goods['specs'] as $prototypeid => $spec){ 
				$oGoods->reduce_store($goods['goodsid'], $prototypeid, $spec, $goods['number']);
			}
		}
		return true;
	}
		
	/***************************************************************************
	 * 支付相关方法
	 ***************************************************************************/
	
	public function pay_back($sn, $result = 1, $trade_no = '', $extra = null){
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['payment_state'] <= 0){
			return $this->rwarn('当前订单已还未进行支付');
		}elseif($orderinfo['payment_state'] == 2 && $result != 1){
			return $this->rwarn('当前订单已付款成功');
		}
		if($orderinfo['delivery_state'] == 3){
			return $this->complete($sn);
		}
		if($result == 1){

			// 增加一条消息
			$oNotice = new Notice();
			$oNotice->add(Notice::PAID, $orderinfo['id']);

			$data = array(
				'state'			=> 1,	// 已付款的订单自动确认
				'payment_state'	=> 2,
				'payment_time'	=> TIME,
			);
			if(!empty($trade_no)){
				$data['trade_no'] = $trade_no;
			}
			$r = $this->update($sn, $data, " AND `state`>=0 AND `payment_state`<2");
		}else{
			$data = array(
					'payment_state'	=> -1,
					'payment_time'	=> TIME,
			);
			if(!empty($trade_no)){
				$data['trade_no'] = $trade_no;
			}
			$r = $this->update($sn, $data, " AND `state`>=0 AND `payment_state`<2");
		}
		if($r > 0){
			return $this->update_paylog($sn, $result, $extra);
		}
		return $r;
	}

	public function send_back($sn, $trade_no = ''){
		##^^ 能到这一步，肯定是成功的
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['payment_state'] == 2){
			return true;
		}
		$data = array(
			'payment_state'	=> 2,	// 已发货，肯定已付款
			'payment_time'	=> TIME,
		);
		if(!empty($trade_no)){
			$data['trade_no'] = $trade_no;
		}
		return $this->update($sn, $data);
	}

	public function receive_back($sn, $trade_no = ''){
		##^^ 能到这一步，肯定是成功的
		$orderinfo = $this->get_order_by_sn($sn);
		if($orderinfo['payment_state'] == 2 && $orderinfo['delivery_state'] == 3){
			return $this->complete($sn);
		}

		// 增加一条消息
		$oNotice = new Notice();
		$oNotice->add(Notice::RECEIVE, $orderinfo['id']);

		$data = array(
			'payment_state'	=> 2,	// 买家已收货，肯定已付款
			'delivery_state'=> 3,
			'delivery_time'	=> TIME,
		);
		if(!empty($trade_no)){
			$data['trade_no'] = $trade_no;
		}
		return $this->update($sn, $data);
	}

	public function add_paylog($userinfo, $sn){
		$orderinfo = $this->get_order_by_sn($sn);
		$data = array(
			'sn'		=> $sn,
			'userid'	=> $userinfo['userid'],
			'username'	=> $userinfo['username'],
			'payment'	=> $orderinfo['payment'],
			'paytime'	=> date('Y-m-d H:i:s'),
			'cost'		=> $orderinfo['cost'],
			'state'		=> 0,
			'extra'		=> '',
			'backtime'	=> '',
		);
		$logid = $this->db->replace($this->tb_paylog, $data);
		if($logid > 0){

			// 增加一条消息
			$oNotice = new Notice();
			$oNotice->add(Notice::PAYING, $orderinfo['id']);

			return $this->db->update($this->tb_order, array('sn' => $sn), array(
				'state' => 1,			// 将订单置为已确认
				'payment_state' => 1,	// 支付中
				'payment_time'	=> TIME,
				'updatetime'	=> TIME,
			));
		}
		return -1;
		
	}
	
	public function update_paylog($sn, $state, $extra = ''){
		$state = $state == 1 ? 1 : -1;
		$r = $this->db->update($this->tb_paylog, array('sn' => $sn), array(
			'state' 	=> $state,
			'backtime'	=> date('Y-m-d H:i:s'),
			'extra'		=> is_object($extra) ? json_encode($extra) : (is_array($extra) ? serialize($extra) : trim($extra)),
		));
		if($r > 0){
			if($state > 0){
				$state = 2;
			}else{
				$state = -1;
			}
			return $this->db->update($this->tb_order, array('sn' => $orderinfo['sn']), array(
				'payment_state' => $state,
				'payment_time'	=> TIME,
				'updatetime'	=> TIME,
			));
		}
		return -1;
	}
	
	/*******************************************************************************
	 * 统计
	 *******************************************************************************/
	public function state_stat(){
		
		$new			= $this->db->get_counts($this->tbname, array('state' => 0, 'payment_state' => 0, 'delivery_state' => 0));
		$confirmed		= $this->db->get_counts($this->tbname, array('state' => 1, 'payment_state' => 0, 'delivery_state' => 0));
		$paying			= $this->db->get_counts($this->tbname, array('state' => 1, 'payment_state' => 1, 'delivery_state' => 0));
		$paid			= $this->db->get_counts($this->tbname, array('state' => 1, 'payment_state' => 2, 'delivery_state' => 0));
		$distribution	= $this->db->get_counts($this->tbname, array('state' => 1, 'delivery_state' => 1));	// 因为有货到付款，所以，不限定付款状态
		$sent			= $this->db->get_counts($this->tbname, array('state' => 1, 'delivery_state' => 2));	// 因为有货到付款，所以，不限定付款状态
		$receive		= $this->db->get_counts($this->tbname, array('state' => 2, 'delivery_state' => 3));	// 已收货，与“完成”的区别是可以未付款
		$commented		= $this->db->get_counts($this->tbname, array('state' => 3, 'payment_state' => 2, 'delivery_state' => 3));	// 必须“已付款”才能评价
		$states = array(
			'new'			=> empty($new)			? 0 : $new,			// 新订单
			'confirmed'		=> empty($confirmed)	? 0 : $confirmed,	// 已确认
			'paying'		=> empty($paying)		? 0 : $paying,		// 付款中
			'paid'			=> empty($paid)			? 0 : $paid,		// 已付款
			'distribution'	=> empty($distribution)	? 0 : $distribution,// 已配货
			'sent'			=> empty($sent)			? 0 : $sent,		// 已发货
			'receive'		=> empty($receive)		? 0 : $receive,		// 已收货
			'commented'		=> empty($commented)	? 0 : $commented,	// 已评价
		);
		return $states;
	}
}
?>